package com.dangf.app.launcher.utils.caleader

import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*

/**
 * @author nanchen
 * @date 16-8-10 上午11:36
 */
class CalendarUtil
/**
 * 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数
 * dayCyl5:与1900年1月31日相差的天数,再加40 ?
 *
 * @param cal
 * @return
 */
(
        /**
         * 用于记录当前处理的时间
         */
        private val mCurrenCalendar: Calendar) {

    /**
     * 计算得到农历的年份
     */
    private val mLuchYear: Int
    /**
     * 计算得到农历的月份
     */
    private val mLuchMonth: Int

    /**
     * 计算得到农历的日期
     */
    private val mLuchDay: Int

    /**
     * 用于标识是事为闰年
     */
    private var isLoap: Boolean = false

    /**
     * 传回农历 y年的生肖
     *
     * @return 传回农历 y年的生肖
     */
    fun animalsYear(): String {
        val Animals = arrayOf("鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪")
        return Animals[(mLuchYear - 4) % 12]
    }

    // ====== 传入 offset 传回干支, 0=甲子
    fun cyclical(): String {
        val num = mLuchYear - 1900 + 36
        return cyclicalm(num)
    }

    init {
        var leapMonth = 0
        var baseDate: Date? = null
        try {
            baseDate = chineseDateFormat.parse("1900年1月31日")
        } catch (e: ParseException) {
            e.printStackTrace() // To change body of catch statement use
            // Options | File Templates.
        }

        // 求出和1900年1月31日相差的天数
        var offset = ((mCurrenCalendar.time.time - baseDate!!.time) / 86400000L).toInt()
        // 用offset减去每农历年的天数
        // 计算当天是农历第几天
        // i最终结果是农历的年份
        // offset是当年的第几天
        var iYear: Int
        var daysOfYear = 0
        iYear = 1900
        while (iYear < 2050 && offset > 0) {
            daysOfYear = yearDays(iYear)
            offset -= daysOfYear
            iYear++
        }
        if (offset < 0) {
            offset += daysOfYear
            iYear--
        }
        // 农历年份
        mLuchYear = iYear

        leapMonth = leapMonth(iYear) // 闰哪个月,1-12
        isLoap = false

        // 用当年的天数offset,逐个减去每月（农历）的天数，求出当天是本月的第几天
        var iMonth = 1
        var daysOfMonth = 0
        while (iMonth < 13 && offset > 0) {
            // 闰月
            if (leapMonth > 0 && iMonth == leapMonth + 1 && !isLoap) {
                --iMonth
                isLoap = true
                daysOfMonth = leapDays(mLuchYear)
            } else
                daysOfMonth = monthDays(mLuchYear, iMonth)

            offset -= daysOfMonth
            // 解除闰月
            if (isLoap && iMonth == leapMonth + 1)
                isLoap = false
            if (!isLoap) {
            }
            iMonth++
        }
        // offset为0时，并且刚才计算的月份是闰月，要校正
        if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
            if (isLoap) {
                isLoap = false
            } else {
                isLoap = true
                --iMonth
            }
        }
        // offset小于0时，也要校正
        if (offset < 0) {
            offset += daysOfMonth
            --iMonth

        }
        mLuchMonth = iMonth
        mLuchDay = offset + 1
    }

    /**
     * 用于显示农历的初几这种格式
     *
     * @return 农历的日期
     */
    override fun toString(): String {
        var message = ""
        // int n = mLuchDay % 10 == 0 ? 9 : mLuchDay % 10 - 1;
        message = getChinaCalendarMsg(mLuchYear, mLuchMonth, mLuchDay)
        if (message.isNullOrEmpty()) {
            val solarMsg = SolarTermsUtil(mCurrenCalendar).solartermsMsg
            // 判断当前日期是否为节气
            if (!solarMsg.isNullOrEmpty()) {
                message = solarMsg
            } else {
                /**
                 * 判断当前日期是否为公历节日
                 */
                val gremessage = GregorianUtil(mCurrenCalendar).gremessage
                message = if (!gremessage.isNullOrEmpty()) {
                    gremessage
                } else if (mLuchDay == 1) {
                    CHINESE_NUMBER[mLuchMonth - 1] + "月"
                } else {
                    getChinaDayString(mLuchDay)
                }

            }
        }
        return message
    }

    /**
     * 返回农历的年月日
     *
     * @return 农历的年月日格式
     */
    val day: String
        get() {
            return (if (isLoap) "闰" else "") + CHINESE_NUMBER[mLuchMonth - 1] + "月" + getChinaDayString(mLuchDay)
        }

    /**
     * 用于获取中国的传统节日
     *
     * @param month 农历的月
     * @param day   农历日
     * @return 中国传统节日
     */
    private fun getChinaCalendarMsg(year: Int, month: Int, day: Int): String {
        var message = ""
        if (month == 1 && day == 1) {
            message = "春节"
        } else if (month == 1 && day == 15) {
            message = "元宵"
        } else if (month == 5 && day == 5) {
            message = "端午"
        } else if (month == 7 && day == 7) {
            message = "七夕"
        } else if (month == 8 && day == 15) {
            message = "中秋"
        } else if (month == 9 && day == 9) {
            message = "重阳"
        } else if (month == 12 && day == 8) {
            message = "腊八"
        } else {
            if (month == 12) {
                if (monthDays(year, month) == 29 && day == 29 || monthDays(year, month) == 30 && day == 30) {
                    message = "除夕"
                }
            }
        }
        return message
    }

    companion object {
        /**
         * 用于保存中文的月份
         */
        private val CHINESE_NUMBER = arrayOf("一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊")

        /**
         * 用于保存展示周几使用
         */
        private val WEEK_NUMBER = arrayOf("日", "一", "二", "三", "四", "五", "六")

        private val LUNAR_INFO = longArrayOf(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0)

        /**
         * 转换为2012年11月22日格式
         */
        private val chineseDateFormat = SimpleDateFormat(
                "yyyy年MM月dd日")
        /**
         * 转换为2012-11-22格式
         */
        private val simpleDateFormat = SimpleDateFormat(
                "yyyy-MM-dd")

        /**
         * 传回农历 year年的总天数
         *
         * @param year 将要计算的年份
         * @return 返回传入年份的总天数
         */
        private fun yearDays(year: Int): Int {
            var i: Int
            var sum = 348
            i = 0x8000
            while (i > 0x8) {
                if ((LUNAR_INFO[year - 1900]).toInt() and i != 0) sum += 1
                i = i shr 1
            }
            return sum + leapDays(year)
        }

        /**
         * 传回农历 year年闰月的天数
         *
         * @param year 将要计算的年份
         * @return 返回 农历 year年闰月的天数
         */
        private fun leapDays(year: Int): Int {
            return if (leapMonth(year) != 0) {
                if ((LUNAR_INFO[year - 1900]).toInt() and 0x10000 != 0)
                    30
                else
                    29
            } else
                0
        }

        /**
         * 传回农历 year年闰哪个月 1-12 , 没闰传回 0
         *
         * @param year 将要计算的年份
         * @return 传回农历 year年闰哪个月 1-12 , 没闰传回 0
         */
        private fun leapMonth(year: Int): Int {
            return (LUNAR_INFO[year - 1900] and 0xf).toInt()
        }

        /**
         * 传回农历 year年month月的总天数
         *
         * @param year  将要计算的年份
         * @param month 将要计算的月份
         * @return 传回农历 year年month月的总天数
         */
        private fun monthDays(year: Int, month: Int): Int {
            return if ((LUNAR_INFO[year - 1900]).toInt() and (0x10000 shr month) == 0)
                29
            else
                30
        }

        // ====== 传入 月日的offset 传回干支, 0=甲子
        private fun cyclicalm(num: Int): String {
            val Gan = arrayOf("甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸")
            val Zhi = arrayOf("子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥")

            return Gan[num % 10] + Zhi[num % 12]
        }

        /**
         * 返化成中文格式
         *
         * @param day
         * @return
         */
        fun getChinaDayString(day: Int): String {
            val chineseTen = arrayOf("初", "十", "廿", "卅")
            val n = if (day % 10 == 0) 9 else day % 10 - 1
            if (day > 30)
                return ""
            return if (day == 10)
                "初十"
            else
                chineseTen[day / 10] + CHINESE_NUMBER[n]
        }

        /**
         * 把calendar转化为当前年月日
         *
         * @param calendar Calendar
         * @return 返回成转换好的 年月日格式
         */
        fun getDay(calendar: Calendar): String {
            return simpleDateFormat.format(calendar.time)
        }

        /**
         * 用于比对二个日期的大小
         *
         * @param compareDate 将要比对的时间
         * @param currentDate 当前时间
         * @return true 表示大于当前时间 false 表示小于当前时间
         */
        fun compare(compareDate: Date, currentDate: Date): Boolean {
            return chineseDateFormat.format(compareDate).compareTo(
                    chineseDateFormat.format(currentDate)) >= 0
        }

        /**
         * 获取当前周几
         *
         * @param calendar
         * @return
         */
        fun getWeek(calendar: Calendar): String {
            return "周" + WEEK_NUMBER[calendar.get(Calendar.DAY_OF_WEEK) - 1] + ""
        }

        /**
         * 将当前时间转换成要展示的形式
         *
         * @param calendar
         * @return
         */
        fun getCurrentDay(calendar: Calendar): String {
            return "${CalendarUtil(calendar).cyclical()}(${CalendarUtil(calendar).animalsYear()})年${CalendarUtil(calendar).day}"
//            return getDay(calendar) + " 农历" + CalendarUtil(calendar).day + " " + getWeek(calendar)
        }
    }
}